package edu.uestc.gene.entity;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import edu.uestc.gene.model.Tool;
import edu.uestc.gene.scripts.combination.entity.CombinedGene;

/**
 * @author Carl
 * 
 *         2013-10-28
 */
public class DataCollector implements Serializable {

	/**
	 * 
	 */
	private static final long serialVersionUID = 1L;

	public static final String DGFILENAME = "./drug_gene.txt";
	public static final String DAFILENAME = "./drug_ADR.txt";
	// public static final String DGFILENAME = "./DG.txt";
	// public static final String DAFILENAME = "./DA.txt";
	public static final String IDFILENAME = "./3_ID.txt";
	public static final String BADDFILENAME = "./gene2ADR.badd";
	public static final String COMBINEDGENE = "./CombinedGeneGroup.txt";

	private List<Drug> drugs;// 所有药物
	private List<Gene> genes;// 所有基因
	private List<AdverseDrugReaction> adrs;// 所有副作用
	private List<CombinedGene> combinedGenes;// 所有可合并基因

	private static DataCollector collector;

	private DataCollector() {
	}

	public static DataCollector getInstance() {
		if (collector == null) {
			collector = new DataCollector();
		}
		return collector;
	}

	public void init(boolean needCombine) {
		drugs = new ArrayList<Drug>();
		genes = new ArrayList<Gene>();
		adrs = new ArrayList<AdverseDrugReaction>();
		combinedGenes = new ArrayList<CombinedGene>();
		initDG();
		initDA();
		initID();
		if (needCombine) {
			initCG();
		}
	}

	/**
	 * 
	 */
	private void initDG() {
		List<String> dg = Tool.getAllInfoByLine(DGFILENAME);
		int size = dg.size();
		for (int i = 0; i < size; i++) {
			String line = dg.get(i);
			String drug = line.substring(0, line.indexOf(","));
			Drug newDrug = new Drug(drug);
			String[] restGenes = line.substring(line.indexOf(",") + 1).split(
					",");
			for (int j = 0; j < restGenes.length; j++) {
				Gene newGene = new Gene(restGenes[j]);
				newGene.addDrug(newDrug);
				newDrug.addGene(newGene);
				int index = genes.indexOf(newGene);
				if (index == -1) {
					genes.add(newGene);
				} else {
					Gene g = genes.get(index);
					g.addDrug(newDrug);
					genes.set(index, g);
				}
			}
			drugs.add(newDrug);
		}
	}

	/**
	 * 
	 */
	private void initDA() {
		List<String> da = Tool.getAllInfoByLine(DAFILENAME);
		int size = da.size();
		for (int i = 0; i < size; i++) {
			String line = da.get(i);
			String drug = line.substring(0, line.indexOf(","));
			Drug currentDrug = drugs.get(drugs.indexOf(new Drug(drug)));
			String[] restADRs = line.substring(line.indexOf(",") + 1)
					.split(",");
			for (int j = 0; j < restADRs.length; j++) {
				AdverseDrugReaction newADR = new AdverseDrugReaction(
						restADRs[j]);
				currentDrug.addADR(newADR);
				int index = adrs.indexOf(newADR);
				if (index == -1) {// 如果是新的ADR则添加，否则修改这个ADR（添加对应药物）
					newADR.addDrug(currentDrug);
					adrs.add(newADR);
				} else {
					newADR = adrs.get(index);
					newADR.addDrug(currentDrug);
					adrs.set(index, newADR);
				}
			}
		}
	}

	/**
	 * 
	 */
	private void initCG() {
		List<String> cg = Tool.getAllInfoByLine(COMBINEDGENE);
		int size = cg.size();
		for (int i = 0; i < size; i++) {
			CombinedGene combinedGene = new CombinedGene("_Gene_" + (i + 1));
			String[] genes_str = cg.get(i).split(",");
			for (int j = 0; j < genes_str.length; j++) {
				Gene gene = genes.get(genes.indexOf(new Gene(genes_str[j])));
				combinedGene.addGene(gene);
				genes.remove(gene);
			}
			combinedGene.combine();
			genes.add(combinedGene);
			combinedGenes.add(combinedGene);
		}
	}

	/**
	 * 
	 */
	private void initID() {
		List<String> id = Tool.getAllInfoByLine(IDFILENAME);
		int size = id.size();
		for (int i = 0; i < size; i++) {
			String[] line = id.get(i).split(",");
			int index = adrs.indexOf(new AdverseDrugReaction(line[0]));
			if (index == -1) {// 在3_ID文件中有的ADR编号在DA文件中不存在。
				continue;
			}
			AdverseDrugReaction adr = adrs.get(index);
			adr.setAlias(line[1]);
		}
	}

	public void write(DataCollector collecter) {
		File f = new File(BADDFILENAME);
		FileOutputStream fos = null;
		ObjectOutputStream oos = null;
		try {
			fos = new FileOutputStream(f);
			oos = new ObjectOutputStream(fos);
			oos.writeObject(collecter);
			System.out.println("数据文件\"gene2ADR.badd\"写入成功！");
		} catch (FileNotFoundException e) {
			System.err.println("找不到文件!\n" + e);
			f.delete();
			return;
		} catch (IOException e) {
			f.delete();
			System.err.println("文件写入错误!\n" + e);
			return;
		} finally {
			try {
				oos.close();
				fos.close();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}
	}

	public void generatCombineGARalation() {
		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < adrs.size(); i++) {
			AdverseDrugReaction currentADR = adrs.get(i);
			sb.append(currentADR.getName() + ",");
			Set<Gene> adr_genes = new HashSet<Gene>();
			for (int j = 0; j < currentADR.getDrugs().size(); j++) {
				adr_genes.addAll(currentADR.getDrugs().get(j).getDrug_genes());
			}
			for (Gene g : adr_genes) {
				sb.append(g.getName() + ",");
			}
			sb.append("\n");
		}
		Tool.writeText(sb.toString(), "E:\\Saves\\gene\\newRelation_t.txt",
				false);
	}

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		DataCollector dc = DataCollector.getInstance();
		dc.init(false);
		// dc.generatCombineGARalation();
		dc.write(dc);
	}

	public List<Drug> getDrugs() {
		return drugs;
	}

	public List<Gene> getGenes() {
		return genes;
	}

	public List<AdverseDrugReaction> getAdrs() {
		return adrs;
	}

	public List<CombinedGene> getCombinedGenes() {
		return combinedGenes;
	}

}
